package utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
/**
 * This class supplies static utilities for converting between byte arrays, strings
 * and integers, as well as reading byte arrays from files.
 * @author yuvalshu
 *
 */
public class ByteArrUtils {
	/**
	 * Create a byte array representation of an ascii string
	 * @param str
	 * @return byte[]
	 * @throws UnsupportedEncodingException
	 */
	public static byte[] AsciiStringToByteArray(String str) throws UnsupportedEncodingException{
		byte[] b = str.getBytes("ASCII");
		return b;
	}
	
	/**
	 * Read a file into a byte array
	 * 
	 * @param file
	 * @return byte[]
	 * @throws UnsupportedEncodingException
	 * @throws IOException
	 */
	public static byte[] ByteArrayFromFile(File file) throws UnsupportedEncodingException, IOException { 
		InputStream is = new FileInputStream(file);

		// Get the size of the file
		long length = file.length();

		// Cannot create an array using a long type.
		// It needs to be an int type.
		// Before converting to an int type, check
		// to ensure that file is not larger than Integer.MAX_VALUE.
		if (length > Integer.MAX_VALUE) {
			throw new IOException("Could not completely read file, file to big to be converted to array "+file.getName());
			// File is too large
		}

		// Create the byte array to hold the data
		byte[] bytes = new byte[(int)length];

		// Read in the bytes
		int offset = 0;
		int numRead = 0;
		while (offset < bytes.length
           && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) {
			offset += numRead;
		}

		// Ensure all the bytes have been read in
		if (offset < bytes.length) {
			throw new IOException("Could not completely read file "+file.getName());
		}

		// Close the input stream and return bytes
		is.close();
		
		return bytes;
	}
	
	/**
	 * Convert a byte array to it's ascii hex string representations
	 * @param byteArr
	 * @return string
	 */
	public static String ByteArrayToHexString(byte[] byteArr){
		  String result = "";
		  for (int i=0; i < byteArr.length; i++) {
		    result +=
		          Integer.toString( ( byteArr[i] & 0xff ) + 0x100, 16).substring( 1 );
		  }
		  return result;
		}


	/**
	 * convert a ascii hex string to it's byte array representation
	 * @param s
	 * @return byte[]
	 */
	public static byte[] hexStringToByteArray(String s) {
	    int len = s.length();
	    byte[] data = new byte[len / 2];
	    for (int i = 0; i < len; i += 2) {
	        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
	                             + Character.digit(s.charAt(i+1), 16));
	    }
	    return data;
	}
	
	/**
	 * convert a 4-byte integer into a byte array
	 * @param value
	 * @return byte[]
	 */
    public static byte[] intToByteArray(int value) {
    	return ByteBuffer.allocate(4).putInt(value).array();
    }
    
    /**
     * convert a byte array into it's integer representation
     * @param byteArr
     * @return integer
     */
    public static int byteArrayToInt(byte[] byteArr){
    	ByteBuffer bb = ByteBuffer.wrap(byteArr);
    	int i = bb.getInt();
    	return i;
    }
}
